package com.mochat.mochat.common.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class QrcodeUtils {

    /**
     * 画二维码
     *
     * @param qrcodePath 存放二维码路径
     * @param content    二维码内容
     * @param height     二维码高度
     * @param width      二维码宽度
     */
    public static void drawQrcode(String qrcodePath, String content, int height, int width) {
        try {
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
            //设置UTF-8， 防止中文乱码
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            //设置二维码四周白色区域的大小
            hints.put(EncodeHintType.MARGIN, 1);
            //设置二维码的容错性
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            //画二维码，记得调用multiFormatWriter.encode()时最后要带上hints参数，不然上面设置无效
            BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            //qrcFile用来存放生成的二维码图片（无logo，无文字）
            File qrcodeFile = QrcodeUtils.findFile(qrcodePath);
            //开始画二维码
            MatrixToImageWriter.writeToFile(bitMatrix, "png", qrcodeFile);
        } catch (WriterException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 给二维码图片添加Logo
     *
     * @param qrCodePath 二维码路径
     * @param logoPath   logo路径
     * @param logoConfig logo 配置文件
     */
    public static void addLogoToQRCode(String qrCodePath, String logoPath, String logoQrcodePath, LogoConfig logoConfig) {
        try {
            File qrCodeFile = new File(qrCodePath);
            File logoFile = new File(logoPath);

            if (!qrCodeFile.isFile() || !logoFile.isFile()) {
                System.out.print("file not find origial file !");
                System.exit(0);
            }

            //读取二维码图片，并构建绘图对象
            BufferedImage image = ImageIO.read(qrCodeFile);
            Graphics2D g = image.createGraphics();
            //读取logo文件
            BufferedImage logo = ImageIO.read(logoFile);
            //设置logo的位置
            int widthLogo = image.getWidth() / logoConfig.getLogoPart();
            int heightLogo = image.getWidth() / logoConfig.getLogoPart(); // 保持二维码是正方形的
            // 计算图片放置位置（居中）
            int x = (image.getWidth() - widthLogo) / 2;
            int y = (image.getHeight() - heightLogo) / 2;

            // 开始绘制图片
            g.drawImage(logo, x, y, widthLogo, heightLogo, null);
            g.drawRoundRect(x, y, widthLogo, heightLogo, 10, 10);
            g.setStroke(new BasicStroke(logoConfig.getBorder()));
            g.setColor(logoConfig.getBorderColor());
            g.drawRect(x, y, widthLogo, heightLogo);
            g.dispose();
            ImageIO.write(image, "jpeg", new File(logoQrcodePath));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * @param qrcodePath     二维码路径
     * @param textQrcodePath 存放文字二维码路径
     * @param qrcodeFontList 文字内容集合
     * @给二维码添加文字
     */
    public static void pressText(String qrcodePath, String textQrcodePath, List<QrcodeFont> qrcodeFontList) {

        try {
            File textQrcodeFile = findFile(qrcodePath);
            Image src = ImageIO.read(textQrcodeFile);
            int imageW = src.getWidth(null);
            int imageH = src.getHeight(null);
            BufferedImage image = new BufferedImage(imageW, imageH+100, BufferedImage.TYPE_INT_RGB);
            Graphics g = image.createGraphics();
            g.setColor(Color.WHITE);//设置笔刷白色
            g.fillRect(0, 0, 600, 600);//填充整个屏幕
            g.drawLine(0, 0, imageW, imageH);
            g.drawImage(src, 0, 0, imageW, imageH, null);
            for (QrcodeFont qrcodeFont : qrcodeFontList) {
                g.setColor(qrcodeFont.getColor());
                Font font = g.getFont();
                g.setFont(new Font(font.getFontName(), qrcodeFont.getFontStyle(), qrcodeFont.getFontSize()));
                int fontWidth = qrcodeFont.getText().length()*qrcodeFont.getFontSize();
                int startX = (imageW - fontWidth)/2;
                g.drawString(qrcodeFont.getText(), startX, qrcodeFont.getStartY());
            }
            g.dispose();
            FileOutputStream out = new FileOutputStream(textQrcodePath);
            ImageIO.write(image, "JPEG", out);
            out.close();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    /**
     * @param filepath
     * @return
     * @查找文件（没有则创建文件）
     */
    public static File findFile(String filepath) {
        File file = new File(filepath);
        if (!file.exists()) {
            file.mkdir();
        }
        return file;
    }

    /**
     * @Author AlphaJunS
     * @Date 11:32 2020/3/8
     * @Description
     * @param srcFiles 压缩的源文件
     * @return void
     */
    public static byte[] zipFile(String[] srcFiles,String[] fileNames){
        try {
                ByteArrayOutputStream fos = new ByteArrayOutputStream();
                ZipOutputStream _zipOut = new ZipOutputStream(fos);
                int index = 0;
                for( String src : srcFiles){
                    URL url = new URL(src);
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setUseCaches(false);
                    connection.setConnectTimeout(60 * 1000);
                    connection.setReadTimeout(60 * 1000);
                    InputStream _in = connection.getInputStream();
                    _zipOut.putNextEntry(new ZipEntry(fileNames[index]));
                    int len = 0;
                    byte[] _byte = new byte[1024];
                    while((len = _in.read(_byte)) > 0){
                        _zipOut.write(_byte, 0, len);
                    }
                    _in.close();
                    _zipOut.closeEntry();
                    index++;
                }
                fos.close();
                _zipOut.close();
                return fos.toByteArray();
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        }
        return null;
    }

    /**
     * @Author AlphaJunS
     * @Date 11:33 2020/3/8
     * @Description
     * @param zip 压缩的目的地址
     * @param zipOut
     * @param srcFile 被压缩的文件信息
     * @param path 在zip中的相对路径
     * @return void
     */
    private static void handlerFile(String zip , ZipOutputStream zipOut , File srcFile , String path) throws IOException {
        System.out.println(" begin to compression file[" + srcFile.getName() + "]");
        if( !"".equals(path) && ! path.endsWith(File.separator)){
            path += File.separator ;
        }
        if( ! srcFile.getPath().equals(zip) ){
            if( srcFile.isDirectory() ){
                File[] _files = srcFile.listFiles();
                if( _files.length == 0 ){
                    zipOut.putNextEntry(new ZipEntry( path + srcFile.getName() + File.separator));
                    zipOut.closeEntry();
                }else{
                    for( File _f : _files ){
                        handlerFile( zip ,zipOut , _f , path + srcFile.getName() );
                    }
                }
            }else{
                InputStream _in = new FileInputStream(srcFile) ;
                zipOut.putNextEntry(new ZipEntry(path + srcFile.getName()));
                int len = 0 ;
                byte[] _byte = new byte[1024];
                while( (len = _in.read(_byte)) > 0  ){
                    zipOut.write(_byte, 0, len);
                }
                _in.close();
                zipOut.closeEntry();
            }
        }
    }

}

